//
//  ViewController.m
//  viewTest
//
//  Created by seonwoo Kang on 2014. 1. 14..
//  Copyright (c) 2014년 seonwoo Kang. All rights reserved.
//

#import "ViewController.h"
#import <ESTBeaconManager.h>
#import "Triangle.h"
#import "BeaconData.h"

#define ROAD_RANGE 30 //길과 떨어진 간격
#define ACC_SENSITIVITY 1.2 // 가속도계 민감도
#define BEACON_SENSITIVITY 20 // 비콘 튄 범위
#define BEACON_JUPM 5

@interface ViewController ()<ESTBeaconManagerDelegate>

@property (nonatomic, strong) ESTBeaconManager* beaconManager;
@property (nonatomic, strong) UIImageView* positionDot; //삼각측량된 점

@property (nonatomic, strong) UIImageView* beacon1Position; //비콘 위치 정해서 지도에 보여주기
@property (nonatomic, strong) UIImageView* beacon2Position;
@property (nonatomic, strong) UIImageView* beacon3Position;
@property (nonatomic, strong) UIImageView* beacon4Position; //비콘 위치 정해서 지도에 보여주기
@property (nonatomic, strong) UIImageView* beacon5Position;
@property (nonatomic, strong) UIImageView* beacon6Position;

@property (nonatomic, strong) ESTBeacon* beacon1; //비콘1


@property float rowRate;
@property float columnRate;


@end

@implementation ViewController

- (void)viewDidLoad
{
    [_mainView addSubview:_background]; //mainView에 백그라운드 이미지 넣기
    
    [self setupDot];
    [self setupManager];
    [self setupBeaconPosition];
    
    //NSLog(@"%@",NSStringFromCGRect([_mainView bounds]));
    
    self.mapDataToGrid = [[MapDatatoGrid alloc] init];
    self.map = [self.mapDataToGrid getMapDatatoGrid];
    
    self.rowRate = 350;
    self.columnRate = 3.5;
    
    //==========================================================
    
    currentMaxAccelX = 0;
    currentMaxAccelY = 0;
    currentMaxAccelZ = 0;

    self.motionManager = [[CMMotionManager alloc] init];
    self.motionManager.accelerometerUpdateInterval = 0.2;

    [self.motionManager startAccelerometerUpdatesToQueue:[NSOperationQueue currentQueue]
                                             withHandler:^(CMAccelerometerData *accelerometerData, NSError *error) {
                                                 [self outputAccelertionData:accelerometerData.acceleration];
                                                 if(error){
                                                     
                                                     NSLog(@"%@", error);
                                                 }
                                             }];
    
    _locationManager=[[CLLocationManager alloc] init];
	_locationManager.desiredAccuracy = kCLLocationAccuracyBest;
	_locationManager.headingFilter = 1;
    _locationManager.delegate = self;
	[_locationManager startUpdatingHeading];

}

- (char)checkMap:(int)x and:(int)y
{
    if(x<321 && y<422){
        int i = [self.mapDataToGrid gridWidth]*y + x;
        unsigned char result = self.map[i];
        return result;
    }
    return '9';
}

- (void)setupDot // 삼각측량 결과점
{
    self.positionDot = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"dot1.png"]];
    [self.positionDot setCenter:self.view.center];
    [self.positionDot setAlpha:1.0f];
    
    [_mainView addSubview:self.positionDot];
}

- (void)setupBeaconPosition //비콘 위치 정해서 지도에 표시해주기
{
    self.beacon1Position = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"mint.jpg"]];
    self.beacon2Position = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"purple.jpg"]];
    self.beacon3Position = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"blue.jpg"]];
    self.beacon4Position = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"mint.jpg"]];
    self.beacon5Position = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"purple.jpg"]];
    self.beacon6Position = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"blue.jpg"]];
    
    [self.beacon1Position setCenter:_mainView.center];
    [self.beacon2Position setCenter:_mainView.center];
    [self.beacon3Position setCenter:_mainView.center];
    [self.beacon4Position setCenter:_mainView.center];
    [self.beacon5Position setCenter:_mainView.center];
    [self.beacon6Position setCenter:_mainView.center];
    
    [self.beacon1Position setAlpha:1.0f];
    [self.beacon2Position setAlpha:1.0f];
    [self.beacon3Position setAlpha:1.0f];
    [self.beacon4Position setAlpha:1.0f];
    [self.beacon5Position setAlpha:1.0f];
    [self.beacon6Position setAlpha:1.0f];

    
    [_mainView addSubview:self.beacon1Position];
    [_mainView addSubview:self.beacon2Position];
    [_mainView addSubview:self.beacon3Position];
    [_mainView addSubview:self.beacon4Position];
    [_mainView addSubview:self.beacon5Position];
    [_mainView addSubview:self.beacon6Position];
    
    
    self.beacon1Position.center = CGPointMake(10,10); // mint 64328
    self.beacon2Position.center = CGPointMake(10, 400);//purple 18020
    self.beacon3Position.center = CGPointMake(310, 420);//blue 23162
    self.beacon4Position.center = CGPointMake(300,110);//mint2 64102
    self.beacon5Position.center = CGPointMake(10, 200);//purple2 46531
    self.beacon6Position.center = CGPointMake(300, 300);//blue 21014
    

}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

- (void)setupManager
{
    // create manager instance
    self.beaconManager = [[ESTBeaconManager alloc] init];
    self.beaconManager.delegate = self;
    
    // create sample region object (you can additionaly pass major / minor values)
    ESTBeaconRegion* region = [[ESTBeaconRegion alloc] initRegionWithIdentifier:@"EstimoteSampleRegion"];
    
    // start looking for estimote beacons in region
    // when beacon ranged beaconManager:didRangeBeacons:inRegion: invoked
    [self.beaconManager startRangingBeaconsInRegion:region];
}

- (BeaconData*)setBeaconAndResult:(NSArray *)beacons //비콘 위치잡기 & 삼각측량 반환
{
    int num = [beacons count];
    
    BeaconData *beacon[num];

    for(int i=0; i<num; i++){
        beacon[i] = [[BeaconData alloc] init];
    }
    
    for(int i=0; i<num; i++){ //비콘 위치 지정해주기
        if([[[beacons objectAtIndex:i] major] intValue] == 64328)//mint
        {
            self.beacon1 = [beacons objectAtIndex:i];
            [beacon[i] setX:315];
            [beacon[i] setY:5];
            [beacon[i] setDistance:[self.beacon1.distance floatValue]*self.rowRate];
            NSLog(@"mint (315,5) : %f", [self.beacon1.distance floatValue]*self.rowRate);
            NSLog(@"mint (315,5) : %f", [self.beacon1.distance floatValue]);
        }
        /*else if([[[beacons objectAtIndex:i] major] intValue] == 23162)//blue
        {
            self.beacon1 = [beacons objectAtIndex:i];
            [beacon[i] setX:315];
            [beacon[i] setY:417];
            [beacon[i] setDistance:[self.beacon1.distance floatValue]*self.rowRate];
            NSLog(@"blue (315,417)  : %f", [self.beacon1.distance floatValue]*self.rowRate);
            NSLog(@"blue (315,417)  : %f", [self.beacon1.distance floatValue]);
        }*/
        else if([[[beacons objectAtIndex:i] major] intValue] == 18020)// purple
        {
            self.beacon1 = [beacons objectAtIndex:i];
            [beacon[i] setX:5];
            [beacon[i] setY:206];
            [beacon[i] setDistance:[self.beacon1.distance floatValue]*self.rowRate];
            NSLog(@"purple (315,206) : %f", [self.beacon1.distance floatValue]*self.rowRate);
            NSLog(@"purple (315,206) : %f", [self.beacon1.distance floatValue]);
        }
 /*       else if([[[beacons objectAtIndex:i] major] intValue] == 64102)// mint2
        {
            self.beacon1 = [beacons objectAtIndex:i];
            [beacon[i] setX:5];
            [beacon[i] setY:5];
            [beacon[i] setDistance:[self.beacon1.distance floatValue]*self.rowRate];
            NSLog(@"mint2 (5,5) : %f", [self.beacon1.distance floatValue]*350);
            NSLog(@"mint2 (5,5) : %f", [self.beacon1.distance floatValue]);
        }*/
        else if([[[beacons objectAtIndex:i] major] intValue] == 46531) //purple2
        {
            self.beacon1 = [beacons objectAtIndex:i];
            [beacon[i] setX:315];
            [beacon[i] setY:417];
            [beacon[i] setDistance:[self.beacon1.distance floatValue]*self.rowRate];
            NSLog(@"purple2 (5,206) : %f", [self.beacon1.distance floatValue]*350);
            NSLog(@"purple2 (5,206) : %f", [self.beacon1.distance floatValue]);
        }
       /* else if([[[beacons objectAtIndex:i] major] intValue] == 21014) // blue2
        {
            self.beacon1 = [beacons objectAtIndex:i];
            [beacon[i] setX:315];
            [beacon[i] setY:417];
            [beacon[i] setDistance:[self.beacon1.distance floatValue]*self.rowRate];
            NSLog(@"blue2 (5,417) : %f", [self.beacon1.distance floatValue]*350);
            NSLog(@"blue2 (5,417) : %f", [self.beacon1.distance floatValue]);
        }*/
        
        
    }

    NSArray* beaconArr = [NSArray arrayWithObjects:beacon count:num];
    
    Triangle *trianle = [[Triangle alloc] init];
    BeaconData *beaconData  = [[BeaconData alloc] init];
    
    beaconData = [trianle calculatePositions:beaconArr];
    return beaconData;
}

- (void)drawBeacon:(BeaconData*)beaconData  // 비콘 위치 그리기
{
    int up, down, left, right;
    bool flag = false;
    up = down = left = right = 1;
    
    _lastY = beaconData.getY;
    _lastX = beaconData.getX;
    
    // NSLog(@"beacon : %d, %d", (int)[beaconData getX],(int)[beaconData getY]);
    char check = [self checkMap:(int)[beaconData getX] and:(int)([beaconData getY])];
    NSLog(@"check   : %c",check);
    //self.positionDot.center = CGPointMake((int)[beaconData getX], (int)[beaconData getY]);
    
    if(check == '1')//길 위에 있을때
    {
        self.positionDot.center = CGPointMake((int)[beaconData getX], (int)[beaconData getY]);
        _dirtyPointX = [beaconData getX];
        _dirtyPointY = [beaconData getY];
        
        NSLog(@"1-1 현좌표 : %d, %d", (int)([beaconData getX]),(int)[beaconData getY]);
        NSLog(@"1-1 좌표 수정중 : %d, %d", (int)([beaconData getX]),(int)[beaconData getY]);
        flag = true;
    }
    else if(check == '2' || check== '0')// 빈 공간에 있을때
    {
        for(int i=0; i<ROAD_RANGE; i++){
            //printf("%d",i);
            char check1 = [self checkMap:(int)([beaconData getX]+up) and:(int)([beaconData getY])];
            char check2 = [self checkMap:(int)([beaconData getX]-down) and:(int)([beaconData getY])];
            char check3 = [self checkMap:(int)[beaconData getX] and:(int)([beaconData getY]+right)];
            char check4 = [self checkMap:(int)[beaconData getX] and:(int)([beaconData getY]-left)];
            
            if(check1 == '1'){
                self.positionDot.center = CGPointMake((int)([beaconData getX]+up+5), (int)([beaconData getY]));
                
                _dirtyPointX = [beaconData getX]+up+5;
                _dirtyPointY = [beaconData getY];
                
                NSLog(@"2-1 현좌표 : %d, %d", (int)([beaconData getX]),(int)[beaconData getY]);
                NSLog(@"2-1 좌표 수정중 : %d, %d", (int)([beaconData getX]+up+5),(int)[beaconData getY]);
                flag = true;
                break;
            }
            else if(check2 == '1'){
                self.positionDot.center = CGPointMake((int)([beaconData getX]-down-5), (int)([beaconData getY]));
                
                _dirtyPointX = [beaconData getX]-down-5;
                _dirtyPointY = [beaconData getY];
                
                NSLog(@"2-2 현좌표 : %d, %d", (int)([beaconData getX]),(int)[beaconData getY]);
                NSLog(@"2-2 좌표 수정중 : %d, %d", (int)([beaconData getX]-down-5),(int)[beaconData getY]);
                flag = true;
                break;
            }
            else if(check3 == '1'){
                self.positionDot.center = CGPointMake((int)([beaconData getX]), (int)([beaconData getY]+right+5));
                
                _dirtyPointX = [beaconData getX];
                _dirtyPointY = [beaconData getY]+right+5;
                
                NSLog(@"2-3 현좌표 : %d, %d", (int)([beaconData getX]),(int)[beaconData getY]);
                NSLog(@"2-3 좌표 수정중 : %d, %d", (int)[beaconData getX],(int)([beaconData getY]+right+5));
                flag = true;
                break;
            }
            else if(check4 == '1'){
                self.positionDot.center = CGPointMake((int)([beaconData getX]), (int)([beaconData getY]-left-5));
                
                _dirtyPointX = [beaconData getX];
                _dirtyPointY = [beaconData getY]-left-5;
                
                NSLog(@"2-4 현좌표 : %d, %d", (int)([beaconData getX]),(int)[beaconData getY]);
                NSLog(@"2-4 좌표 수정중 : %d, %d", (int)[beaconData getX],(int)([beaconData getY]-left-5));
                flag = true;
                break;
            }
            up++;
            down++;
            left++;
            right++;
        }
    }
    
    if(flag == false)
    {
        self.positionDot.center = CGPointMake((int)[beaconData getX], (int)[beaconData getY]);
        
        _dirtyPointX = [beaconData getX];
        _dirtyPointY = [beaconData getY];
        
        NSLog(@"3-1 현좌표 : %d, %d", (int)([beaconData getX]),(int)[beaconData getY]);
        NSLog(@"3-1 마지막 좌표 수정중 : %d, %d", (int)([beaconData getX]),(int)[beaconData getY]);
    }

}

//절대값 구하기
float absolute(float a) {
    return a<0 ? -a : a;
}


#pragma mark - ESTBeaconManagerDelegate Implementation
-(void)beaconManager:(ESTBeaconManager *)manager
     didRangeBeacons:(NSArray *)beacons
            inRegion:(ESTBeaconRegion *)region
{
    if([beacons count] >2 )
    {
        NSLog(@"********  start  *********");
        
        BeaconData *beaconData  = [[BeaconData alloc] init];
        beaconData = [self setBeaconAndResult:beacons]; //비콘위치 지정 및 삼각측량 값 가지고 오기
    
        _tempX = abs(_lastX - (int)beaconData.getX); // 최근의 점과 현재점의 절대값을 구하여 차이를 구한다.
        _tempY = abs(_lastY - (int)beaconData.getY);

        NSLog(@"비콘 현재 점 : %f , %f", beaconData.getX , beaconData.getY);
        NSLog(@"비콘 최근 점 : %d , %d", _lastX, _lastY);
        NSLog(@"비콘 점 차이 : %d , %d",_tempX,_tempY);
        
        if(_tempX>BEACON_SENSITIVITY || _tempY>BEACON_SENSITIVITY) //비콘이 확 튀었다.
        {
            NSLog(@"-------------------------------------------------  beacon jump");
            NSLog(@"count : %d", count);
            //NSLog(@"%f , %f , %f",absolute(currentMaxAccelX),absolute(currentMaxAccelY),absolute(currentMaxAccelZ));
            if(absolute(currentMaxAccelX)>ACC_SENSITIVITY || absolute(currentMaxAccelY)>ACC_SENSITIVITY || absolute(currentMaxAccelZ)>ACC_SENSITIVITY)//가속도계가 변했나
            {
                NSLog(@"acc change");
                currentMaxAccelX = currentMaxAccelY = currentMaxAccelZ = 0;
                if(beaconData.getX<=320 && beaconData.getX >=0 && beaconData.getY<=422 && beaconData.getY>=0)
                {
                    [self drawBeacon:beaconData];
                }
                else
                    NSLog(@"out of range");
            }
            else//가속도계 안변함
            {
                NSLog(@"acc No change");
                self.positionDot.center = CGPointMake(_dirtyPointX, _dirtyPointY);
                count++;
            }
            
            if(count >= BEACON_JUPM){
                _lastX = beaconData.getX;
                _lastY = beaconData.getY;
                count = 0;
            }
        }
        else{
            NSLog(@"---------------------------------- beacon silence");
            currentMaxAccelX = currentMaxAccelY = currentMaxAccelZ = 0;
            if(beaconData.getX<=320 && beaconData.getX >=0 && beaconData.getY<=422 && beaconData.getY>=0)
            {
                [self drawBeacon:beaconData];
            }
            else
                NSLog(@"out of range");
        }
        NSLog(@"********  end  *********");
    }
    
    else if([beacons count]>=2)
        NSLog(@"No connect......2");
    else if ([beacons count]>=1)
        NSLog(@"No connect......1");
    else
        NSLog(@"No connect......0");
}

-(void)outputAccelertionData:(CMAcceleration)acceleration
{
    if(fabs(acceleration.x) > fabs(currentMaxAccelX)){
        currentMaxAccelX = acceleration.x;
    }
    if(fabs(acceleration.y) > fabs(currentMaxAccelY)){
        currentMaxAccelY = acceleration.y;
    }
    if(fabs(acceleration.z) > fabs(currentMaxAccelZ)){
        currentMaxAccelZ = acceleration.z;
    }
}


@end
